<template>
  <div class="row q-gutter-lg" :class="align">
    <div v-for="(file, idx) of files" :key="idx">
      <div>
        <q-btn v-if="canPreview(file)" label="预览" color="teal" dense @click="previewAttach(file)" />
        <q-btn
          icon="attachment"
          :label="showFileName(file.filename)"
          outline
          @click="download(file)"
        >
          <q-tooltip>点击下载 {{file.filename}}</q-tooltip>
        </q-btn>
        <q-btn v-if="!readonly" label="删除" color="grey" dense @click="remove(file.url)" />
      </div>
      <div v-if="file.size">SIZE:{{humerSize(file.size)}}</div>
    </div>
    <div>
      <q-btn
        icon="add_to_photos"
        round
        @click.prevent="pickFiles"
        v-if="!readonly"
      >
        <q-tooltip>增加附件</q-tooltip>
      </q-btn>
    </div>

    <q-uploader
      ref="upload"
      url="/upload"
      flat
      multiple
      batch
      accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.dwg,.ai,.cdr,video/*"
      :max-file-size="100 * 1024 * 1024"
      label="上传附件"
      @uploaded="uploaded"
      @added="added"
      style="display: none;"
      :headers="headers"
    />
    <a ref="download" v-show="false" :href="downfile.href" :download="downfile.filename" />

    <q-dialog
      v-model="showDialog"
      persistent
      maximized
    >
      <q-card style="background-color: rgba(130, 130, 130, 1)">
        <q-bar>
          <q-space />
          <!-- <div v-show="previewShow.pdf" class="flex">
            <q-btn label="上一页" color="white" dense flat @click="changePdfPage(-1)" />
            {{pdfConfig.currentPage}} / {{pdfConfig.pageCount}}
            <q-btn label="下一页" color="white" dense flat @click="changePdfPage(1)" />
            <q-separator vertical dark class="q-mx-sm" />
            <q-btn label="缩小" color="white" dense flat @click="changePdfScale(-5)" />
            <q-btn label="恢复" color="white" dense flat @click="changePdfScale()" />
            <q-btn label="放大" color="white" dense flat @click="changePdfScale(5)" />
          </div> -->
          <div v-show="previewShow.pdf" class="flex">
            <q-btn label="上一页" color="white" dense flat @click="pdfEmbedLastPage" />
            {{pdfConfig.pageNum}} / {{pdfConfig.numPages}}
            <q-btn label="下一页" color="white" dense flat @click="pdfEmbedNextPage" />
            <q-separator vertical dark class="q-mx-sm" />
            <q-btn label="缩小" color="white" dense flat @click="pdfEmbedZoomIn" />
            <q-btn label="放大" color="white" dense flat @click="pdfEmbedZoomOut" />
          </div>

          <q-space />
          <q-btn dense flat icon="close" v-close-popup>
            <q-tooltip>关闭</q-tooltip>
          </q-btn>
        </q-bar>

        <q-card-section class="q-pa-none">
          <div v-show="previewShow.docx" style="height: 100%; overflow: scroll;">
            <div ref="docPreview"></div>
          </div>

          <div v-show="previewShow.xlsx" class="bg-white">
            <!-- <div id="luckysheet" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"></div> -->
            <div v-html="xlsxUI"></div>
          </div>

          <!-- <div v-show="previewShow.pdf" class="flex justify-center">
            <pdf
              ref="pdfPreview"
              :src="pdfConfig.url"
              :page="pdfConfig.currentPage"
              @num-pages="pdfConfig.pageCount = $event"
              @page-loaded="pdfConfig.currentPage = $event"
              @loaded="loadPdfHandler"
              :style="{width: $q.screen.xs ? '100%' : '50%'}"
            />
          </div> -->
          <div v-show="previewShow.pdf">
            <div class="pdf-wrap">
              <vue-pdf-embed
                ref="vuePdfRef"
                :source="pdfConfig.source"
                :style="scaleFun"
                :page="pdfConfig.pageNum"
                @loaded="handleDocumentLoad"
              />
            </div>
          </div>

          <div v-show="previewShow.video" class="flex justify-center items-center" style="height: 100%;">
            <video ref="videoPlayer" class="video-js"></video>
          </div>
        </q-card-section>
        <q-ajax-bar
          ref="bar"
          position="bottom"
          color="accent"
          size="6px"
          skip-hijack
        />
      </q-card>
    </q-dialog>

  </div>
</template>

<script>
import { defineComponent, defineAsyncComponent } from 'vue';
import axios from 'axios';
import { defaultOptions, renderAsync } from 'docx-preview';
// import pdf from 'vue-pdf';
// ssr期间会出现ReferenceError: document is not defined，解决不了
// import VuePdfEmbed from 'vue-pdf-embed';

import videojs from 'video.js';
import * as XLSX from 'xlsx';

export default defineComponent({
  components: {
    // pdf
    VuePdfEmbed: defineAsyncComponent(() => import('vue-pdf-embed')) // 使用 Vue 的 defineAsyncComponent 方法来动态加载
  },
  props: {
    attach: Array,
    readonly: {
      type: Boolean,
      default: false
    },
    // 检验引用
    checkQuote: {
      type: Object,
      default: () => {
        return {
          type: '', // 后台对应的检查类型
          exclude_id: '' // 排除检查的id
        }
      }
    },
    position: {
      type: String,
      default: 'center'
    }
  },
  emits: ['done'],
  data () {
    return {
      files: [],
      unlinkFiles: [],
      downfile: {
        href: '',
        filename: ''
      },
      showDialog: false,
      previewShow: {
        docx: false,
        xlsx: false,
        pdf: false,
        video: false
      },
      xlsxUI: '',
      pdfConfig: {
        // url: '',
        // currentPage: 0,
        // pageCount: 0,
        // scale: 100
        source: '', // 预览pdf文件地址
        pageNum: 1, // 当前页面
        scale: 1, // 缩放比例
        numPages: 0, // 总页数
        pdfShow: true // pdf是否显示

      },
      player: null,
      videoOptions: {
        autoplay: true, // 自动播放
        controls: true, // 用户可以与之交互的控件
        loop: true, // 视频一结束就重新开始
        muted: false, // 默认情况下将使所有音频静音
        // aspectRatio: '16:9', // 显示比率
        fullscreen: {
          options: { navigationUI: 'hide' }
        },
        sources: [{
          src: '',
          type: 'video/mp4'
        }]
      },
      promiseResult: null
    }
  },
  beforeUnmount () {
    if (this.player) {
      this.player.dispose()
    }
  },
  mounted () {
    this.files = Object.assign([], this.attach && this.attach.filter(v => !this.unlinkFiles.includes(v.url)));
  },
  methods: {
    do () { // 上传 删除 附件
      return new Promise((resolve, reject) => {
        if (this.unlinkFiles.length > 0) {
          axios.post('/c/system/unlinkFiles', { files: this.unlinkFiles });
        }

        if (this.files.filter(item => item.file).length > 0) {
          this.promiseResult = { resolve, reject };
          this.$refs.upload.upload();
        } else {
          this.$emit('done', this.files);
          resolve(this.files);
        }
      });
    },
    uploaded (info) { // 上传完毕
      const files = JSON.parse(info.xhr.responseText).attachs;
      for (const file of files) {
        const findedfile = this.files.filter(item => {
          return item.file && item.filename === file.filename;
        })[0];
        findedfile.url = file.url;
        delete findedfile.file;
      }

      this.$emit('done', this.files);
      this.promiseResult.resolve(this.files);
    },
    added (files) { // 添加文件
      const self = this;
      // console.log(files);
      files.forEach(file => {
        self.files.push({
          filename: file.name,
          url: '',
          size: file.size,
          type: file.type,
          file
        });
      });
    },
    remove (remoteFile) { // 删除文件
      const self = this;
      this.files = this.files.filter(file => {
        if (file.url === remoteFile) {
          if (file.file) {
            self.$refs.upload.removeFile(file.file);// 从待上传列表中移除
          } else {
            const { type, exclude_id } = this.checkQuote;
            if (type && exclude_id) {
              axios.post('/c/system/checkQuoteFile', { type, exclude_id, file_path: file.url }).then(({ data }) => {
                if (!data.quoted) {
                  self.unlinkFiles.push(file.url);// 添加到待删除任务
                }
              });
            } else {
              this.unlinkFiles.push(file.url);// 添加到待删除任务
            }
          }
          return false;
        } else {
          return true;
        }
      });
    },
    humerSize (size) {
      if (size < 1024) {
        return `${size} B`
      } else if (size < 1024 * 1024) {
        let hs = String(size / 1024).split('.');
        if (hs.length === 2 && hs[1].length > 2) {
          hs = `${hs[0]}.${hs[1].slice(0, 2)}`;
        } else {
          hs = hs.join('.');
        }
        return `${hs} KB`;
      } else {
        let hs = String(size / 1024 / 1024).split('.');
        if (hs.length === 2 && hs[1].length > 2) {
          hs = `${hs[0]}.${hs[1].slice(0, 2)}`;
        } else {
          hs = hs.join('.');
        }
        return `${hs} MB`;
      }
    },
    download (file) {
      if (file.url) {
        this.downfile.href = file.url;
        this.downfile.filename = file.filename;
        this.$nextTick(() => {
          this.$refs.download.click();
        });
      }
    },
    headers () { // 加上用户token
      const items = [];
      if (this.$q.localStorage.getItem('token')) {
        items.push({
          name: 'Authorization',
          value: this.$q.localStorage.getItem('token')
        });
      }
      return items;
    },
    canPreview (file) {
      if (!file.url) {
        return false;
      }
      const fileArr = file.url.split('.');
      const allowType = ['docx', 'xlsx', 'pdf']; // , 'pdf'

      if (fileArr.length > 1 && allowType.indexOf(fileArr[fileArr.length - 1].toLowerCase()) >= 0 || file.type.indexOf('video') === 0) {
        return true;
      } else {
        return false;
      }
    },
    previewAttach (file) {
      const fileArr = file.url.split('.');
      let ext = fileArr[fileArr.length - 1].toLowerCase();
      for (const key in this.previewShow) {
        this.previewShow[key] = false;
      }
      if (file.type.indexOf('video') === 0) { // 视频类
        ext = 'video';
      }

      switch (ext) {
        case 'docx':
          this.previewShow.docx = true;
          this.previewWord(file.url);
          break;
        case 'xlsx':
          this.previewShow.xlsx = true;
          this.previewExcel(file.url);
          break;
        case 'pdf':
          this.previewShow.pdf = true;
          this.previewPdf(file.url);
          break;
        case 'video':
          this.previewShow.video = true;
          this.previewVideo(file);
      }
    },
    previewWord (url) { // 渲染 word 文件内容
      const self = this;
      axios({ method: 'get', responseType: 'blob', url }).then(({ data }) => {
        self.showDialog = true;
        self.$nextTick(() => {
          this.startLoading();
          renderAsync(data, self.$refs.docPreview, null, {
            ignoreWidth: true, // 禁止页面渲染宽度
            ignoreHeight: true, // 禁止页面渲染高度
            experimental: true // 启用实验性功能（制表符停止计算）
          }).then(x => {
            self.stopLoading();
          });
        });
      }).catch(err => {
        // self.$refs.docPreview.innerHTML = '';
        console.log(err);
      });
    },
    previewExcel (url) { // 渲染excel文件
      const self = this;
      this.showDialog = true;
      axios.get(url, {
        responseType: 'arraybuffer' // 设置响应体类型为arraybuffer
      }).then(({ data }) => {
        const workbook = XLSX.read(new Uint8Array(data), { type: 'array' }); // 解析数据
        const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // workbook.SheetNames 下存的是该文件每个工作表名字,这里取出第一个工作表
        self.xlsxUI = XLSX.utils.sheet_to_html(worksheet); // 渲染
      });
    },
    previewPdf (url) { // 预览pdf
      /* this.showDialog = true;
      this.$nextTick(() => {
        this.startLoading();
        this.pdfConfig.url = pdf.createLoadingTask({
          url,
          cMapUrl: 'pdfjs-dist/cmaps/',
          cMapPacked: true
          // CMapReaderFactory
        });
      }); */
      this.showDialog = true;
      this.$nextTick(() => {
        this.pdfConfig.source = url;
        this.pdfConfig.scale = 1;
      });
    },
    changePdfPage (val) { // pdf 翻页
      let page = this.pdfConfig.currentPage + Number(val);
      if (page < 1) page = 1;
      if (page > this.pdfConfig.pageCount) page = this.pdfConfig.pageCount;
      this.pdfConfig.currentPage = page;
    },
    changePdfScale (val) { // pdf 缩放
      if (val) {
        const curWidth = this.$refs.pdfPreview.$el.style.width.replace(/%/, '');
        let scale = Number(curWidth) + Number(val);
        if (scale <= 10) scale = 10;
        this.pdfConfig.scale = scale;
      } else {
        this.pdfConfig.scale = this.$q.screen.xs ? 100 : 50;
      }
      this.$refs.pdfPreview.$el.style.width = this.pdfConfig.scale + '%';
    },
    loadPdfHandler (e) { // pdf加载时
      this.pdfConfig.currentPage = 1; // 加载的时候先加载第一页
      this.stopLoading();
    },
    previewVideo (file) {
      this.showDialog = true;
      this.$nextTick(() => {
        // this.video.src = url;
        this.videoOptions.sources = [{ src: file.url, type: file.type }];
        this.player = videojs(this.$refs.videoPlayer, this.videoOptions, function onPlayerReady () {
          // console.log('onPlayerReady', this);
        });
      });
    },
    // 上一页
    pdfEmbedLastPage () {
      if (this.pdfConfig.pageNum > 1) {
        this.pdfConfig.pageNum -= 1;
      }
    },
    // 下一页
    pdfEmbedNextPage () {
      if (this.pdfConfig.pageNum < this.pdfConfig.numPages) {
        this.pdfConfig.pageNum += 1;
      }
      console.log(this.pdfConfig.pageNum);
    },

    // 放大
    pdfEmbedZoomOut () {
      if (this.pdfConfig.scale < 2) {
        this.pdfConfig.scale += 0.1;
      }
    },
    // 缩小
    pdfEmbedZoomIn () {
      if (this.pdfConfig.scale > 1) {
        this.pdfConfig.scale -= 0.1;
      }
    },
    // pdf加载完事件
    handleDocumentLoad (handle) {
      this.pdfConfig.numPages = handle.numPages;
    },
    showFileName (filename) {
      const arr = filename.split('.');
      let name = '';
      for (let i = 0; i < arr.length - 1; i++) {
        name += arr[i];
      }

      if (name.length > 8) {
        name = `${name.slice(0, 8)}...${arr.length > 1 ? '.' + arr[arr.length - 1] : ''}`;
      } else {
        name = filename;
      }

      return name;
    },
    startLoading () {
      this.$refs.bar.start();
    },
    stopLoading () {
      this.$refs.bar.stop();
    },
    pickFiles () {
      this.$refs.upload.pickFiles();
    }
  },
  computed: {
    align () {
      return this.position === 'center' ? 'justify-center' : this.position === 'left' ? 'justify-start' : 'justify-end';
    },
    scaleFun () {
      return `transform:scale(${this.pdfConfig.scale});margin-top:2%`
    }
  },
  watch: {
    attach (val) {
      this.files = Object.assign([], val && val.filter(v => !this.unlinkFiles.includes(v.url)));
    }
  }
});
</script>

<style lang="scss" scoped>
.vue-pdf-embed {
  text-align: center;
  width: 515px;
  border: 1px solid #e5e5e5;
  margin: 0 auto;
  box-sizing: border-box;
}
.pdf-wrap{
  overflow-y:auto ;
}
</style>
